package com.ynet.middleground.riskmanage.model.worldex;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

import com.ynet.middleground.riskmanage.bean.*;
import com.ynet.middleground.riskmanage.common.SystemConstant;
import com.ynet.middleground.riskmanage.dao.*;
import com.ynet.middleground.riskmanage.mq.producer.WorldexCustomerAnalyticsProducer;
import com.ynet.middleground.riskmanage.bean.*;
import com.ynet.middleground.riskmanage.dto.*;
import com.ynet.middleground.riskmanage.dto.rizhaogang.RizhaoPortDockCompanyInfoDTO;
import org.apache.commons.lang3.StringUtils;
import org.dozer.DozerBeanMapper;
import org.dozer.Mapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.IService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ifp.util.core.DateUtil;
import com.ynet.core.common.BaseReqObj;
import com.ynet.core.exception.BusinessException;
import com.ynet.host.HostConstants;
import com.ynet.middleground.riskmanage.bean.BlchInReq;
import com.ynet.middleground.riskmanage.bean.BlchOutReq;
import com.ynet.middleground.riskmanage.bean.BlchQueryReq;
import com.ynet.middleground.riskmanage.bean.PayableQueryReq;
import com.ynet.middleground.riskmanage.constant.BlchStatusEnum;
import com.ynet.middleground.riskmanage.dto.BlchRespDTO;
import com.ynet.middleground.riskmanage.dto.BlchStatusDTO;
import com.ynet.middleground.riskmanage.dto.PayableDTO;
import com.ynet.middleground.riskmanage.dto.WorldexFileDTO;
import com.ynet.middleground.riskmanage.entity.*;
import com.ynet.middleground.riskmanage.external.MainBusinessConfig;
import com.ynet.middleground.riskmanage.mq.producer.BlchProducer;
import com.ynet.middleground.riskmanage.utils.ApiUtil;
import com.ynet.middleground.riskmanage.utils.BeanUtil;
import com.ynet.middleground.riskmanage.utils.DateUtils;

/**
 * @author liulx
 * @description 全球捷运业务处理 <br>
 *              实现附件通用处理功能
 * @date 2020-08-14 14:48
 */
@Component
public class WorldexModel extends ServiceImpl<WorldexBlchFileMapper, WorldexBlchFile>
    implements IService<WorldexBlchFile> {

    /**
     * 日志打印时显示的名称
     */
    public static final String LOG_NAME = "全球捷运";

    /**
     * 查询应付账款地址
     */
    public static final String URL_QUERY_LIST_PAYABLE = "/Servlet";

    /**
     * 推送保理池状态的地址
     */
    public static final String URL_PUSH_BLCH_STATUS = "/PushServlet";

    /**
     * 0 发票；1 费用确认单
     */
    public static final String NUMBER_ZERO = "0";
    public static final String NUMBER_ONE = "1";

    @Autowired
    private Mapper mapper;

    @Autowired
    private MainBusinessConfig mainBusinessConfig;

    @Autowired
    private ApiUtil apiUtil;

    @Autowired
    private AccountsPayableModel payableModel;

    @Autowired
    private AccountsPayableHistoryModel payableHistoryModel;

    @Autowired
    private WorldexBlchOutModel blchOutModel;

    @Autowired
    private WorldexBlchInModel blchInModel;

    @Autowired
    private BlchProducer blchProducer;

    @Autowired
    private WorldexCustomerAnalyticsProducer worldexCustomerAnalyticsProducer;

    @Autowired
    private WorldexCustomerAnalyticsMapper worldexCustomerAnalyticsMapper;

    @Autowired
    private WorldexCustomerAllMapper worldexCustomerAllMapper;

    @Autowired
    private DozerBeanMapper dozerBeanMapper;

    @Autowired
    private WorldexCustListMapper worldexCustListMapper;

    @Autowired
    private WorldexCustApproveMapper worldexCustApproveMapper;
    @Autowired
    private WorldexCustomerAllLatestMapper worldexCustomerAllLatestMapper;

    /**
     * TODO: 测试专用 测试应付账款，模拟返回数据
     *
     * @return
     */
    public JSONObject testPayableData() {
        String testData =
            "{\"code\":0,\"msg\":\"操作成功\",\"debug\":\"详细错误提示\",\"array\":[{\"cus_no\":\"JXWL01\",\"cus_name\":\"青岛俊鑫国际物流有限公司\",\"bill_no\":\"HLCUTA1200326689\",\"td_no\":\"HLCUTA1200326689\",\"fs_dd\":\"2020-05-21\",\"bill_type\":\"TD\",\"amount\":300,\"crncry\":\"RMB\",\"due_date\":\"2020-06-20\",\"amount_rcv\":300,\"amount_rcv_no\":0,\"attach\":[{\"fileext\":\"jpg\",\"filemd5\":\"74B87337454200D4D33F80C4663DC5E5\",\"fileurl\":\"https://221.0.213.38:8443/qgilloan/AttachServlet?id=74B87337454200D4D33F80C4663DC5E5\"},{\"fileext\":\"jpg\",\"filemd5\":\"74B87337454200D4D33F80C4663DC5E6\",\"fileurl\":\"https://221.0.213.38:8443/qgilloan/AttachServlet?id=74B87337454200D4D33F80C4663DC5E6\"},{\"fileext\":\"jpg\",\"filemd5\":\"74B87337454200D4D33F80C4663DC5E7\",\"fileurl\":\"https://221.0.213.38:8443/qgilloan/AttachServlet?id=74B87337454200D4D33F80C4663DC5E7\"},{\"fileext\":\"jpg\",\"filemd5\":\"74B87337454200D4D33F80C4663DC5E8\",\"fileurl\":\"https://221.0.213.38:8443/qgilloan/AttachServlet?id=74B87337454200D4D33F80C4663DC5E8\"}]}]}";
        JSONObject apiResult = JSONObject.parseObject(testData);
        return apiResult;
    }

    /**
     * 查询应付账款列表
     *
     * @param req 应付账查询信息
     * @return 应付账款列表
     */
    public List<PayableDTO> listPayable(PayableQueryReq req) {
        // 检查日期格式是否为 yyyy-MM-dd
        try {
            DateUtil.parse(req.getStartDate(), DateUtil.FORTER_DATE);
            DateUtil.parse(req.getEndDate(), DateUtil.FORTER_DATE);
            DateUtil.parse(req.getFeesDueDate(), DateUtil.FORTER_DATE);
        } catch (Exception e) {
            throw new BusinessException("日期格式错误，请检查", "ECRM0003");
        }
        Map<String, Object> params = new HashMap<>(8);
        // method 指定为查询应付账款信息
        params.put("method", "GetBillList");
        params.put("cus_name", req.getUserName());
        params.put("td_no", req.getTdNo());
        params.put("crncry", req.getCurrency());
        params.put("fs_dd1", req.getStartDate());
        params.put("fs_dd2", req.getEndDate());
        params.put("endDate", req.getFeesDueDate());

        JSONObject apiResult = apiUtil.sendApiLog("2000", mainBusinessConfig.getWorldexUrl() + URL_QUERY_LIST_PAYABLE,
            null, params, HostConstants.HTTP_METHOD_POST, LOG_NAME, req);
        // JSONObject apiResult = testPayableData();

        Integer code = apiResult.getInteger("code");
        String message = apiResult.getString("msg");
        if (!code.equals(0)) {
            throw new BusinessException(message, String.valueOf(code));
        }

        JSONArray jsonArray = apiResult.getJSONArray("array");
        List<WorldexAccountsPayableResp> payableList = jsonArray.toJavaList(WorldexAccountsPayableResp.class);
        if (payableList == null || payableList.isEmpty()) {
            return Collections.emptyList();
        }
        return processRespListData(payableList, req);
    }

    /**
     * <pre>
     *      处理接口最新返回的数据，并将数据插入历史表中。
     *      针对最新数据处理方式：根据数据中每个业务 id 号，判断是否已经存在于数据库中
     *      如果已存在数据库，则将数据库中的数据更新为最新的数据;
     *      若不存在数据库中，则新增
     * </pre>
     *
     * <note> 应付账款业务主键使用「提单号」 来判断 </note>
     *
     * @param list 接口返回最新应付账款信息
     * @param req 基础请求对象，用于获取请求渠道、操作人等信息
     * @return 应付账款数据传输集合
     * @author liulx
     * @date 2020-08-13 20:40:25
     */
    @Transactional(rollbackFor = Exception.class)
    protected List<PayableDTO> processRespListData(List<WorldexAccountsPayableResp> list, BaseReqObj req) {
        List<PayableDTO> dtoList = new ArrayList<>(list.size());
        // 业务主键 id 缓存
        List<String> checkIds = new ArrayList<>();
        // 待保存的历史数据信息
        List<WorldexAccountsPayableRespHistory> historyList = new ArrayList<>(list.size());
        list.forEach(obj -> {
            // 设置共用字段属性
            WorldexAccountsPayableResp tempObj = BeanUtil.setGenericInfo(obj, req);
            List<WorldexBlchFile> fileList = tempObj.getAttach();
            tempObj.setFiles(JSON.toJSONString(fileList));

            // 转换成历史信息，并添加到历史信息集合中
            WorldexAccountsPayableRespHistory history = mapper.map(tempObj, WorldexAccountsPayableRespHistory.class);

            historyList.add(history);
            // 添加业务主键 id 到集合
            checkIds.add(obj.getTdNo());
            // 转换 DTO 并添加到集合中
            dtoList.add(transformPayableDTO(obj));
        });

        // 保存历史信息表
        payableHistoryModel.saveBatch(historyList);
        LambdaQueryWrapper<WorldexAccountsPayableResp> queryWrapper = new LambdaQueryWrapper<>();
        // 根据业务 id 查询返回数据列表中，已存在于数据库里的数据
        queryWrapper.in(WorldexAccountsPayableResp::getTdNo, checkIds);
        // 数据库中已存在的数据
        List<WorldexAccountsPayableResp> existList = payableModel.list(queryWrapper);

        // 循环判断哪些数据需要更新，哪些是新增
        for (WorldexAccountsPayableResp respObj : list) {
            for (WorldexAccountsPayableResp existObj : existList) {
                // 找到已存在于数据库中的数据，说明需要更新该信息
                // update by liwq on 2021-03-12 start
                // 唯一性不能只看提单号，提单号+币种才可以确定唯一
                if (respObj.getTdNo().equals(existObj.getTdNo()) && respObj.getCrncry().equals(existObj.getCrncry())) {
                    // 将已存在的数据 id，设置到新的数据对象中，按照新的数据对象进行更新
                    respObj.setId(existObj.getId());
                    break;
                }
                // update by liwq on 2021-03-12 end
            }
        }
        // 保存或更新数据
        payableModel.saveOrUpdateBatch(list);
        return dtoList;
    }

    /**
     * 应付账款数据库 entity 转 数据传输对象
     *
     * @param obj 应付账款对象
     * @return 数据传输对象
     */
    protected PayableDTO transformPayableDTO(WorldexAccountsPayableResp obj) {
        PayableDTO dto = new PayableDTO();
        dto.setBillNo(obj.getTdNo());
        dto.setUserNo(obj.getCusNo());
        dto.setUserName(obj.getCusName());
        dto.setCheckNo(obj.getBillNo());
        dto.setShipDate(DateUtils.toDate(obj.getFsDd(), DateUtil.FORTER_DATE));
        dto.setType(obj.getBillType());
        dto.setAmount(Double.parseDouble(obj.getAmount()));
        dto.setCurrencType(obj.getCrncry());
        dto.setExpDate(DateUtils.toDate(obj.getDueDate(), DateUtil.FORTER_DATE));
        dto.setYsAmount(Double.parseDouble(obj.getAmountRcv()));
        dto.setWsAmount(Double.parseDouble(obj.getAmountRcvNo()));
        dto.setInvoiceNo(obj.getFpNo());
        List<WorldexFileDTO> fileList = obj.getAttach().stream().map(file -> {
            WorldexFileDTO fileDTO = new WorldexFileDTO();
            fileDTO.setDevName(file.getFileext());
            fileDTO.setMd5(file.getFilemd5());
            fileDTO.setAddress(file.getFileurl());
            return fileDTO;
        }).collect(Collectors.toList());
        dto.setFiles(fileList);
        return dto;
    }

    /**
     * 查询保理池业务出入池状态
     *
     * @param req 查询保理池业务出入池状态请求信息
     * @return 出入池状态数据
     */
    public BlchStatusDTO queryBlchStatus(BlchQueryReq req) {
        // 若是发票，根据单据编号+序列号可确定唯一；
        // 若是费用确认单，根据单据编号+序列号+币种确定唯一；
        BlchStatusDTO dto = new BlchStatusDTO();
        LambdaQueryWrapper<WorldexBlchOut> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(WorldexBlchOut::getOrderNum, req.getOrderNum());
        queryWrapper.eq(WorldexBlchOut::getSerialNo, req.getSerialNo());

        if (NUMBER_ONE.equals(req.getOrderType())) {
            queryWrapper.eq(WorldexBlchOut::getCurrency, req.getCurrency());
        }
        WorldexBlchOut blchOut = null;
        List<WorldexBlchOut> list = blchOutModel.list(queryWrapper);
        if (list.size() > 0) {
            blchOut = list.get(0);
        }
        if (blchOut != null) {
            dto.setOrderNum(blchOut.getOrderNum());
            dto.setSerialNo(blchOut.getSerialNo());
            dto.setState(blchOut.getStatus());
            dto.setDate(blchOut.getOutPoolDate());
            return dto;
        }
        LambdaQueryWrapper<WorldexBlchIn> queryWrapperIn = new LambdaQueryWrapper<>();
        queryWrapperIn.eq(WorldexBlchIn::getOrderNum, req.getOrderNum());
        queryWrapperIn.eq(WorldexBlchIn::getSerialNo, req.getSerialNo());
        if (NUMBER_ONE.equals(req.getOrderType())) {
            queryWrapperIn.eq(WorldexBlchIn::getCurrency, req.getCurrency());
        }
        WorldexBlchIn blchIn = null;
        List<WorldexBlchIn> worldexBlchInList = blchInModel.list(queryWrapperIn);
        if (worldexBlchInList.size() > 0) {
            blchIn = worldexBlchInList.get(0);
        }
        if (blchIn != null) {
            dto.setOrderNum(blchIn.getOrderNum());
            dto.setSerialNo(blchIn.getSerialNo());
            dto.setState(blchIn.getStatus());
            dto.setDate(blchIn.getNewPoolDate());
            return dto;
        }
        throw new BusinessException("该保理池业务数据不存在", "ECCT0600");
    }

    /**
     * 入池数据落库
     *
     * <pre>
     *     MQ 推送时使用，由于 MQ 无法对外网使用，故不使用，暂保留
     * </pre>
     *
     * @param data MQ 接收到的数据
     * @return 已经落库的数据
     */
    @Transactional(rollbackFor = Exception.class)
    public WorldexBlchIn saveBlchIn(Map<String, Object> data) {
        WorldexBlchIn worldexBlchIn = mapper.map(data, WorldexBlchIn.class);
        worldexBlchIn.setGmtCreate(LocalDateTime.now());
        worldexBlchIn.setGmtModified(LocalDateTime.now());
        blchInModel.save(worldexBlchIn);
        return worldexBlchIn;
    }

    /**
     * 出池池数据落库
     *
     * <pre>
     *     MQ 推送时使用，由于 MQ 无法对外网使用，故不使用，暂保留
     * </pre>
     *
     * @param data MQ 接收到的数据
     * @return 已经落库的数据
     */
    @Transactional(rollbackFor = Exception.class)
    public WorldexBlchOut saveBlchOut(Map<String, Object> data) {
        WorldexBlchOut worldexBlchOut = mapper.map(data, WorldexBlchOut.class);
        worldexBlchOut.setGmtCreate(LocalDateTime.now());
        worldexBlchOut.setGmtModified(LocalDateTime.now());
        blchOutModel.save(worldexBlchOut);
        return worldexBlchOut;
    }

    /**
     * 入池数据落库保存
     *
     * @param blchInReq 保理池入池数据参数信息
     * @return 落库后的 id 标识
     */
    @Transactional(rollbackFor = Exception.class)
    public BlchRespDTO saveBlchIn(BlchInReq blchInReq) {
        // add by liwq on 2022-07-08 start
        // 增加校验。下一提单数据（如客户是核心企业，则非必填，否则必填）
        if (StringUtils.isEmpty(blchInReq.getBuyerName())) {
            throw new BusinessException("请上送买方名称", "ECCT0604");
        }
        LambdaQueryWrapper<WorldexCustomerAllLatest> latestQueryWrapper = new LambdaQueryWrapper<>();
        latestQueryWrapper.eq(WorldexCustomerAllLatest::getCustomerName, blchInReq.getBuyerName());
        List<WorldexCustomerAllLatest> latests = worldexCustomerAllLatestMapper.selectList(latestQueryWrapper);
        if (latests.size() == 0 || latests == null) {
            throw new BusinessException("客户:" + blchInReq.getBuyerName() + "还未推送", "ECCT0605");
        }
        WorldexCustomerAllLatest latest = null;
        if (latests.size() != 0 && latests != null) {
            latest = latests.get(0);
            // 1 代表是核心企业。0不是核心企业。如客户是核心企业，则下一单号非必填，否则必填
            if ("0".equals(latest.getCoreCompany())) {
                if (StringUtils.isEmpty(blchInReq.getNextOrderNum())) {
                    throw new BusinessException("该客户不是核心企业，下一提单号必须上送", "ECCT0605");
                }
            }
        }
        // add by liwq on 2022-07-08 end

        if (!BlchStatusEnum.RECEIVE_STATUS_NEW.getCode().equals(blchInReq.getStatus())
            && !BlchStatusEnum.RECEIVE_STATUS_UPDATE.getCode().equals(blchInReq.getStatus())) {
            throw new BusinessException("状态参数值有误", "ECCT0603");
        }

        // update by liwq on 2021-03-11 start
        // 若是发票，根据单据编号+序列号可确定唯一；
        // 若是费用确认单，根据单据编号+序列号+币种确定唯一；
        WorldexBlchIn worldexBlchIn = mapper.map(blchInReq, WorldexBlchIn.class);
        LambdaQueryWrapper<WorldexBlchIn> queryWrapper = new LambdaQueryWrapper<>();
        if (NUMBER_ZERO.equals(blchInReq.getOrderType())) {
            queryWrapper.eq(WorldexBlchIn::getOrderNum, blchInReq.getOrderNum());
            queryWrapper.eq(WorldexBlchIn::getSerialNo, blchInReq.getSerialNo());
        }
        if (NUMBER_ONE.equals(blchInReq.getOrderType())) {
            if (StringUtils.isEmpty(blchInReq.getCurrency())) {
                throw new BusinessException("单据类型为费用确认单，币种必填", "ECCT0609");
            }
            queryWrapper.eq(WorldexBlchIn::getOrderNum, blchInReq.getOrderNum());
            queryWrapper.eq(WorldexBlchIn::getSerialNo, blchInReq.getSerialNo());
            queryWrapper.eq(WorldexBlchIn::getCurrency, blchInReq.getCurrency());
        }
        List<WorldexBlchIn> list = blchInModel.list(queryWrapper);
        WorldexBlchIn one = null;
        if (list.size() > 0) {
            one = list.get(0);
        }
        // update by liwq on 2021-03-11 end

        // 判断新入池的数据是否已经存在
        if (one != null && BlchStatusEnum.RECEIVE_STATUS_NEW.getCode().equals(blchInReq.getStatus())) {
            throw new BusinessException("该保理池业务入池数据已存在", "ECCT0601");
        }
        if (blchInReq.getImageUrl() != null) {
            worldexBlchIn.setImageUrl(JSON.toJSONString(blchInReq.getImageUrl()));
        }
        // 接受的入池数据默认状态为待审批
        worldexBlchIn.setStatus(BlchStatusEnum.IN_APPROVE.getCode());
        worldexBlchIn.setCreateBy(blchInReq.getOperationUserId());
        worldexBlchIn.setModifiedBy(blchInReq.getOperationUserId());
        // 数据已存在，更新数据
        if (one != null && BlchStatusEnum.RECEIVE_STATUS_UPDATE.getCode().equals(blchInReq.getStatus())) {
            // 状态 00: 入池成功、01: 入池失败、02：入池审批
            // 检查数据是否已经入池成功，成功不允许更新
            if (BlchStatusEnum.IN_SUCCESS.getCode().equals(one.getStatus())) {
                throw new BusinessException("该保理池业务入池数据已入池成功，无法更新", "ECCT0604");
            }
            worldexBlchIn.setId(one.getId());
            blchInModel.updateById(worldexBlchIn);
        } else {
            worldexBlchIn.setGmtModified(LocalDateTime.now());
            worldexBlchIn.setGmtCreate(LocalDateTime.now());
            blchInModel.save(worldexBlchIn);
        }
        BlchRespDTO dto = new BlchRespDTO();
        dto.setId(worldexBlchIn.getId());

        // 将数据放入 MQ 推送至渠道
        Map<String, Object> mqData = JSONObject.parseObject(JSONObject.toJSONString(worldexBlchIn), Map.class);
        mqData.put("traceId", blchInReq.getTraceId());
        mqData.put("requestTime", blchInReq.getRequestTime());
        // 移除无关参数
        mqData.remove("reason");
        mqData.remove("newPoolDate");
        mqData.remove("channel");
        mqData.remove("gmtCreate");
        mqData.remove("createBy");
        mqData.remove("gmtModified");
        mqData.remove("modifiedBy");
        blchProducer.sendMessagesBlchIn(mqData);
        return dto;
    }

    /**
     * 出池数据落库保存
     *
     * @param blchOutReq 保理池出池数据参数信息
     * @return 落库后的 id 标识
     */
    @Transactional(rollbackFor = Exception.class)
    public BlchRespDTO saveBlchOut(BlchOutReq blchOutReq) {
        if (!BlchStatusEnum.RECEIVE_STATUS_NEW.getCode().equals(blchOutReq.getStatus())
            && !BlchStatusEnum.RECEIVE_STATUS_UPDATE.getCode().equals(blchOutReq.getStatus())) {
            throw new BusinessException("状态参数值有误", "ECCT0603");
        }

        // update by liwq on 2021-03-11 start
        // 若是发票，根据单据编号+序列号可确定唯一；
        // 若是费用确认单，根据单据编号+序列号+币种确定唯一；
        WorldexBlchOut worldexBlchOut = mapper.map(blchOutReq, WorldexBlchOut.class);
        LambdaQueryWrapper<WorldexBlchOut> queryWrapper = new LambdaQueryWrapper<>();
        if (NUMBER_ZERO.equals(blchOutReq.getOrderType())) {
            queryWrapper.eq(WorldexBlchOut::getOrderNum, blchOutReq.getOrderNum());
            queryWrapper.eq(WorldexBlchOut::getSerialNo, blchOutReq.getSerialNo());
        }
        if (NUMBER_ONE.equals(blchOutReq.getOrderType())) {
            if (StringUtils.isEmpty(blchOutReq.getCurrency())) {
                throw new BusinessException("单据类型为费用确认单，币种必填", "ECCT0609");
            }
            queryWrapper.eq(WorldexBlchOut::getOrderNum, blchOutReq.getOrderNum());
            queryWrapper.eq(WorldexBlchOut::getSerialNo, blchOutReq.getSerialNo());
            queryWrapper.eq(WorldexBlchOut::getCurrency, blchOutReq.getCurrency());
        }
        List<WorldexBlchOut> list = blchOutModel.list(queryWrapper);
        WorldexBlchOut one = null;
        if (list.size() > 0) {
            one = list.get(0);
        }
        // update by liwq on 2021-03-11 end

        // 判断新入池的数据是否已经存在
        if (one != null && BlchStatusEnum.RECEIVE_STATUS_NEW.getCode().equals(blchOutReq.getStatus())) {
            throw new BusinessException("该保理池业务出池数据已存在", "ECCT0602");
        }
        // 接受的出池数据默认状态为待审批
        worldexBlchOut.setStatus(BlchStatusEnum.OUT_APPROVE.getCode());
        worldexBlchOut.setCreateBy(blchOutReq.getOperationUserId());
        worldexBlchOut.setModifiedBy(blchOutReq.getOperationUserId());
        // 数据已存在，更新数据
        if (one != null && BlchStatusEnum.RECEIVE_STATUS_UPDATE.getCode().equals(blchOutReq.getStatus())) {
            // 检查数据是否已经入池成功，成功不允许更新
            if (BlchStatusEnum.OUT_SUCCESS.getCode().equals(one.getStatus())) {
                throw new BusinessException("该保理池业务出池数据已正常出池，无法更新", "ECCT0605");
            }
            worldexBlchOut.setId(one.getId());
            blchOutModel.updateById(worldexBlchOut);
        } else {
            worldexBlchOut.setGmtCreate(LocalDateTime.now());
            worldexBlchOut.setGmtModified(LocalDateTime.now());
            blchOutModel.save(worldexBlchOut);
        }

        BlchRespDTO dto = new BlchRespDTO();
        dto.setId(worldexBlchOut.getId());

        // 将数据放入 MQ 推送至渠道
        Map<String, Object> mqData = JSONObject.parseObject(JSONObject.toJSONString(worldexBlchOut), Map.class);
        mqData.put("traceId", blchOutReq.getTraceId());
        mqData.put("requestTime", blchOutReq.getRequestTime());
        // 移除无关参数
        mqData.remove("reason");
        mqData.remove("outPoolDate");
        mqData.remove("channel");
        mqData.remove("gmtCreate");
        mqData.remove("createBy");
        mqData.remove("gmtModified");
        mqData.remove("modifiedBy");
        blchProducer.sendMessagesBlchOut(mqData);
        return dto;
    }

    /**
     * 接收全球捷运推送的客户分析数据
     *
     * @create songyf
     * @param req 客户分析数据参数信息
     * @return 响应结果数据
     */
    @Transactional(rollbackFor = Exception.class)
    public String receiveCustomerAnalytics(WorldexCustomerAnalyticsReq req) {
        WorldexCustomerAnalytics worldexCustomerAnalytics = mapper.map(req, WorldexCustomerAnalytics.class);
        worldexCustomerAnalytics.setCreateBy(req.getOperationUserId());
        worldexCustomerAnalytics.setGmtCreate(LocalDateTime.now());
        worldexCustomerAnalyticsMapper.insert(worldexCustomerAnalytics);
        Map<String, Object> mqData =
            JSONObject.parseObject(JSONObject.toJSONString(worldexCustomerAnalytics), Map.class);
        mqData.remove("id");
        mqData.remove("createBy");
        mqData.remove("gmtCreate");
        mqData.put("traceId", req.getTraceId());
        mqData.put("requestTime", req.getRequestTime());
        mqData.put("operationUserId", req.getOperationUserId());
        worldexCustomerAnalyticsProducer.sendMessagesCustomerAnalytics(mqData);
        String returnsResult = SystemConstant.SYSTEM_SUCCESS;
        return returnsResult;
    }

    /**
     * 接收全球捷运推送的客户全量数据
     *
     * @create songyf
     * @param req 客户分析数据参数信息
     * @return 响应结果数据
     */
    @Transactional(rollbackFor = Exception.class)
    public String receiveCustomerAll(WorldexCustomerAllListReq req) {
        List<WorldexCustomerAll> worldexCustomerAllList =
            BeanUtil.mapList(dozerBeanMapper, req.getCustomerList(), WorldexCustomerAll.class);
        LocalDateTime time = LocalDateTime.now();
        for (int i = 0; i < worldexCustomerAllList.size(); i++) {
            worldexCustomerAllList.get(i).setChannel(req.getChannel());
            worldexCustomerAllList.get(i).setCreateBy(req.getOperationUserId());
            worldexCustomerAllList.get(i).setGmtCreate(time);
            worldexCustomerAllList.get(i).setTraceId(req.getTraceId());
        }
        worldexCustomerAllMapper.insertBatch(worldexCustomerAllList);
        worldexCustomerAllLatestMapper.updateFlag();
        worldexCustomerAllLatestMapper.insertOrUpdateBatch(
            BeanUtil.mapList(dozerBeanMapper, worldexCustomerAllList, WorldexCustomerAllLatest.class));
        Map<String, Object> mqData = JSONObject.parseObject(JSONObject.toJSONString(req), Map.class);
        mqData.remove("id");
        mqData.remove("createBy");
        mqData.remove("gmtCreate");
        worldexCustomerAnalyticsProducer.sendMessagesCustomerAll(mqData);
        String returnsResult = SystemConstant.SYSTEM_SUCCESS;
        return returnsResult;
    }

    /* 客户名单查询
    *
    * @param req
    * @return
    */
    @Transactional(rollbackFor = Exception.class)
    public List<CustListRespDTO> getCustList(CustListQueryReq req) {
        Map<String, Object> params = new HashMap<>(8);
        // method 指定为查询客户名单
        params.put("method", "GetCustList");
        params.put("cus_no", req.getCustNo());
        params.put("cus_name", req.getCusName());

        JSONObject apiResult = apiUtil.sendApiLog("2003", mainBusinessConfig.getWorldexUrl() + URL_QUERY_LIST_PAYABLE,
            null, params, HostConstants.HTTP_METHOD_POST, LOG_NAME, req);

        Integer code = apiResult.getInteger("code");
        String message = apiResult.getString("msg");
        if (!code.equals(0)) {
            throw new BusinessException(message, String.valueOf(code));
        }
        JSONArray jsonArray = apiResult.getJSONArray("array");
        List<CustListRespDTO> custListRespDTOs = jsonArray.toJavaList(CustListRespDTO.class);
        if (custListRespDTOs == null || custListRespDTOs.isEmpty()) {
            return Collections.emptyList();
        }
        // 将全球捷运的返回结果入库
        List<WorldexCustListRecord> records =
            BeanUtil.mapList(dozerBeanMapper, custListRespDTOs, WorldexCustListRecord.class);
        for (WorldexCustListRecord c : records) {
            c.setCreateBy(req.getOperationUserId());
            c.setGmtModified(LocalDateTime.now());
            c.setGmtCreate(LocalDateTime.now());
            c.setModifiedBy(req.getOperationUserId());
            c.setChannel(req.getChannel());
            worldexCustListMapper.insert(c);
        }
        return custListRespDTOs;
    }

    /**
     * 客户审核结果推送
     *
     * @param req
     * @return
     */
    public Boolean pushCustApproveResult(CustApproveListReq req) {
        if (req.getApproveResult() == null || req.getApproveResult().size() == 0) {
            return false;
        }
        // if (req.getApproveResult().size() > 50) {
        // throw new BusinessException("请一次上传少于10条数据", "ECCT0000");
        // }

        String batchNumber = UUID.randomUUID().toString();
        // 调用全球捷运的参数
        List<Object> list = new ArrayList<>(10);
        Map<String, Object> temp = null;
        for (CustApproveReq custApproveReq : req.getApproveResult()) {
            temp = new HashMap<>(8);
            temp.put("cus_no", custApproveReq.getCusNo());
            temp.put("cus_name", custApproveReq.getCusName());
            temp.put("approve_state", custApproveReq.getApproveState());
            temp.put("black_state", custApproveReq.getBlackState());
            temp.put("approve_time", custApproveReq.getApproveTime());
            list.add(temp);
        }
        Map<String, Object> params = new HashMap<>(8);
        // method 指定为审核结果推送
        params.put("method", "cust_approve");
        params.put("array", list);

        JSONObject apiResult = apiUtil.sendApiLog("2004", mainBusinessConfig.getWorldexUrl() + URL_PUSH_BLCH_STATUS,
            null, params, HostConstants.HTTP_METHOD_POST, LOG_NAME, req);

        Integer code = apiResult.getInteger("code");
        String message = apiResult.getString("msg");
        if (!code.equals(0)) {
            throw new BusinessException(message, String.valueOf(code));
        }

        // 将请求信息入库记录
        List<WorldexCustApproveRecord> records =
            BeanUtil.mapList(dozerBeanMapper, req.getApproveResult(), WorldexCustApproveRecord.class);
        for (WorldexCustApproveRecord record : records) {
            record.setCreateBy(req.getOperationUserId());
            record.setGmtCreate(LocalDateTime.now());
            record.setChannel(req.getChannel());
            record.setResultCode(code);
            record.setBatchNumber(batchNumber);
            record.setModifiedBy(req.getOperationUserId());
            record.setGmtModified(LocalDateTime.now());
            worldexCustApproveMapper.insert(record);
        }
        return true;
    }

}
